﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace System.Net.Http
{
    public class TokenManager : ITokenManager
    {
        /// <summary>
        /// UTF8
        /// </summary>
        private static readonly UTF8Encoding Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false,
                                                                         throwOnInvalidBytes: true);

        private const string Purpose = "WebApi_Token_Purpose";

        /// <summary>
        /// 根据Token获取身份信息。获取失败返回Empty
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public IdentityInfo GetIdentity(string token)
        {
            if (string.IsNullOrEmpty(token))
            {
                return IdentityInfo.Empty;
            }
            try
            {
                string json = Unprotect(token);
                return json.JsonToObject<IdentityInfo>();
            }
            catch (Exception ex)
            {
                string message = string.Format("Error When Get Identity By Token,The token value is \r\n[{0}]", token);
                ex.Error(message, "IdentityError");
                return IdentityInfo.Empty;
            }
        }

        private string Protect(string data)
        {
            byte[] purposeBytes = Encoding.GetBytes(Purpose);
            byte[] unprotectedBytes = Encoding.GetBytes(data);
            byte[] protectedBytes = ProtectedData.Protect(unprotectedBytes, purposeBytes,DataProtectionScope.LocalMachine);
            return Convert.ToBase64String(protectedBytes);
        }

        /// <summary>
        /// 创建此身份信息的Token
        /// </summary>
        /// <param name="identityInfo"></param>
        /// <returns></returns>
        public string CreateToken(IdentityInfo identityInfo)
        {
            string data = identityInfo.ToJson();
            string token = Protect(data);
            return token;
        }

        private string Unprotect(string protectedValue)
        {
            byte[] purposeBytes = Encoding.GetBytes(Purpose);
            byte[] protectedBytes = Convert.FromBase64String(protectedValue);
            byte[] unprotectedBytes = ProtectedData.Unprotect(protectedBytes, purposeBytes,DataProtectionScope.LocalMachine);
            return Encoding.GetString(unprotectedBytes);
        }

        public const string TokenName = "Token";

        public string TokenHeaderName
        {
            get { return TokenName; }
        }
    }
}